﻿/******************************************************************************
 * 【本类功能概述】                                 					      *
 *  版权所有（C）2017-20XX，匠梦科技                                         *
 *  保留所有权利。                                                            *
 ******************************************************************************
 *  作者 : <hughjk>
 *  创建时间:2018年4月23日 17:19:25
 *  文件描述:扩展代码
 *****************************************************************************/

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public static class ExtendTool
{
    #region Transform

    public static void _SetX(this Transform tf, float x)
    {
        Vector3 pos = tf.position;
        pos.x = x;
        tf.position = pos;
    }

    public static void _SetY(this Transform tf, float y)
    {
        Vector3 pos = tf.position;
        pos.y = y;
        tf.position = pos;
    }

    public static void _SetZ(this Transform tf, float z)
    {
        Vector3 pos = tf.position;
        pos.z = z;
        tf.position = pos;
    }

    #endregion Transform

    #region 字符串

    public static string GetNumFormat(this int num)
    {
        return string.Format("{0:n0}", num);
    }

    /// <summary>
    /// 字符串转int
    /// </summary>
    /// <param name="s">字符串</param>
    /// <returns></returns>
    public static int toInt(this string s)
    {
        return int.Parse(s);
    }

    public static int toInt(this int s)
    {
        return s;
    }

    public static float toFloat(this string s)
    {
        return float.Parse(s);
    }

    public static string toString(this string s)
    {
        return s;
    }

    /// <summary>
    /// 字符串转intList
    /// </summary>
    /// <param name="s">字符串</param>
    /// <param name="gap">分隔符</param>
    /// <returns></returns>
    public static int[] toIntArr(this string s, char gap)
    {
        string[] satt = s.Split(gap);
        int item = 0;
        int[] list = new int[satt.Length];
        for (int i = 0; i < satt.Length; i++)
        {
            try
            {
                item = int.Parse(satt[i]);
            }
            catch (System.Exception ex)
            {
                Debug.LogError(ex.ToString());
            }
            list[i] = item;
        }
        return list;
    }

    /// <summary>
    /// 字符串转intList
    /// </summary>
    /// <param name="s">字符串</param>
    /// <param name="gap">分隔符</param>
    /// <returns></returns>
    public static List<int> toIntList(this string s, char gap)
    {
        string[] satt = s.Split(gap);
        int item = 0;
        List<int> list = new List<int>();
        for (int i = 0; i < satt.Length; i++)
        {
            try
            {
                item = int.Parse(satt[i]);
            }
            catch (System.Exception ex)
            {
                Debug.LogError(ex.ToString());
            }
            list.Add(item);
        }
        return list;
    }

    /// <summary>
    /// 字符串转FloatList
    /// </summary>
    /// <param name="s">字符串</param>
    /// <param name="gap">分隔符</param>
    /// <returns></returns>
    public static List<float> toFloatList(this string s, char gap)
    {
        string[] satt = s.Split(gap);
        float item = 0;
        List<float> list = new List<float>();
        for (int i = 0; i < satt.Length; i++)
        {
            try
            {
                item = float.Parse(satt[i]);
            }
            catch (System.Exception ex)
            {
                Debug.LogError(ex.ToString());
            }
            list.Add(item);
        }
        return list;
    }

    /// <summary>
    /// 取其中的几位,并转换为整形
    /// </summary>
    /// <param name="s"></param>
    /// <param name="str">从0开始</param>
    /// <param name="len"></param>
    /// <returns></returns>
    public static int subToInt(this string s, int str, int len)
    {
        string z = s.Substring(str, len);
        return z.toInt();
    }

    /// <summary>
    /// 取其中的几位列如:123456.setSub(2,2);=&gt;34
    /// </summary>
    /// <param name="s"></param>
    /// <param name="str"></param>
    /// <param name="len"></param>
    /// <returns></returns>
    public static int sub(this int num, int str, int len)
    {
        if (len == 0)
        {
            return 0;
        }
        int newNum = num;
        int zlen = newNum.Length();
        int zend = zlen - str - len;
        zend = zend < 0 ? 0 : zend;
        if (zend > zlen)
        {
            debug.log("超过截取范围!!!!");
            return 0;
        }
        newNum /= (int)Math.Pow(10, zend);
        newNum %= (int)Math.Pow(10, len);
        return newNum;
    }

    /// <summary>
    /// 替换其中的几位,列如:123456.setSub(2,78);=&gt;127856
    /// </summary>
    /// <param name="s"></param>
    /// <param name="str"></param>
    /// <param name="len"></param>
    /// <returns></returns>
    public static int setSub(this int num, int str, int news)
    {
        int mlen = num.Length();
        int nlen = news.Length();
        int zend = mlen - str - nlen;
        zend = zend < 0 ? 0 : zend;
        int baseDigit = (int)Math.Pow(10, zend);
        int dislodge = num.sub(str, nlen) * baseDigit;//抹去位的值
        news *= baseDigit;//得到位

        num = num - dislodge + news;
        return num;
    }

    /// <summary>
    /// 获取一个整形的位长度
    /// </summary>
    /// <param name="num"></param>
    /// <returns></returns>
    public static int Length(this int num)
    {
        int zlen = 0;
        float u = num;
        for (int i = 0; i < 99; i++)
        {
            if (u < 1)
            {
                break;
            }
            u = u / 10;
            zlen++;
        }
        return zlen;
    }

    public static int toInt(this long num)
    {
        return (int)num;
    }

    private static bool isNumStringPool = false;
    private static Dictionary<int, string> NumStringPool = new Dictionary<int, string>();
    private static Dictionary<long, string> longNumStringPool = new Dictionary<long, string>();

    /// <summary>
    /// 常用数值缓存
    /// </summary>
    /// <param name="num"></param>
    /// <returns></returns>
    public static string toString(this int num)
    {
        if (!isNumStringPool)
        {
            isNumStringPool = true;
            for (int i = -150; i < 150; i++)
            {
                NumStringPool.Add(i, i.ToString());
            }
        }
        if (num < -150 || num >= 150)
        {
            string v;
            if (!NumStringPool.TryGetValue(num, out v))
            {
                v = num.ToString();
                NumStringPool.Add(num, v);
            }
            return v;
        }
        else
        {
            return NumStringPool[num];
        }
    }

    public static string toString(this long num)
    {
        string v;
        if (!longNumStringPool.TryGetValue(num, out v))
        {
            v = num.ToString();
            longNumStringPool.Add(num, v);
        }
        return v;
    }

    #region 查询关键字方法

    private static int[] GetKmpNext(string pattern)
    {
        int[] next = new int[pattern.Length];
        next[0] = -1;
        if (pattern.Length < 2) return next;
        next[1] = 0;
        int i = 2, j = 0;
        while (i < pattern.Length)
        {
            if (pattern[i - 1] == pattern[j])
            {
                next[i++] = ++j;
            }
            else
            {
                j = next[j];
                if (j == -1)
                {
                    next[i++] = ++j;
                }
            }
        }
        return next;
    }

    /// <summary>
    /// 查询关键字 模糊查询 PC测试 "LevenshteinDis";{ "Ls", "La", "Ldd", "asde", "Lfasde", "in" } ,1000次 3毫秒
    /// </summary>
    /// <param name="source">原字符串</param>
    /// <param name="keywords">关键字列表用|分开</param>
    /// <returns>如果存在关键字返回true，反之返回false。</returns>
    public static bool t_find_Key(this string source, string[] keywords)
    {
        int wordCount = keywords.Length;
        int[][] nexts = new int[wordCount][];
        int i = 0;
        for (i = 0; i < wordCount; i++)
        {
            nexts[i] = GetKmpNext(keywords[i]);
        }
        i = 0;
        int[] j = new int[nexts.Length];
        while (i < source.Length)
        {
            for (int k = 0; k < wordCount; k++)
            {
                if (source[i] == keywords[k][j[k]])
                {
                    j[k]++;
                }
                else
                {
                    j[k] = nexts[k][j[k]];
                    if (j[k] == -1)
                    {
                        j[k]++;
                    }
                }
                if (j[k] >= keywords[k].Length)
                {
                    return true;
                }
            }
            i++;
        }
        return false;
    }

    #endregion 查询关键字方法

    #region 字符串匹配度查询

    /// <summary>
    /// 字符串匹配度查询 返回0-1的一个值,1表示完全匹配 PC测试 "LevenshteinDis"; "Levenshte";, 1000次 7毫秒
    /// </summary>
    /// <param name="source"></param>
    /// <param name="str2"></param>
    /// <returns></returns>
    public static float t_similarity(this string str1, string str2)
    {
        return LevenshteinDistance.Ins.LevenshteinDistancePercent(str1, str2);
    }

    /// <summary>
    /// 编辑距离算法
    /// </summary>
    private class LevenshteinDistance
    {
        private static LevenshteinDistance ins = null;

        public static LevenshteinDistance Ins
        {
            get
            {
                if (ins == null)
                {
                    return new LevenshteinDistance();
                }
                return ins;
            }
        }

        /// <summary>
        /// 取最小的一位数
        /// </summary>
        /// <param name="first"></param>
        /// <param name="second"></param>
        /// <param name="third"></param>
        /// <returns></returns>
        public int LowerOfThree(int first, int second, int third)
        {
            int min = first;
            if (second < min)
                min = second;
            if (third < min)
                min = third;
            return min;
        }

        public int Levenshtein_Distance(string str1, string str2)
        {
            int[,] Matrix;
            int n = str1.Length;
            int m = str2.Length;

            int temp = 0;
            char ch1;
            char ch2;
            int i = 0;
            int j = 0;
            if (n == 0)
            {
                return m;
            }
            if (m == 0)
            {
                return n;
            }
            Matrix = new int[n + 1, m + 1];

            for (i = 0; i <= n; i++)
            {
                //初始化第一列
                Matrix[i, 0] = i;
            }

            for (j = 0; j <= m; j++)
            {
                //初始化第一行
                Matrix[0, j] = j;
            }

            for (i = 1; i <= n; i++)
            {
                ch1 = str1[i - 1];
                for (j = 1; j <= m; j++)
                {
                    ch2 = str2[j - 1];
                    if (ch1.Equals(ch2))
                    {
                        temp = 0;
                    }
                    else
                    {
                        temp = 1;
                    }
                    Matrix[i, j] = LowerOfThree(Matrix[i - 1, j] + 1, Matrix[i, j - 1] + 1, Matrix[i - 1, j - 1] + temp);
                }
            }

            //for (i = 0; i <= n; i++)
            //{
            //    for (j = 0; j <= m; j++)
            //    {
            //        Console.Write(" {0} ", Matrix[i, j]);
            //    }
            //    Console.WriteLine("");
            //}
            return Matrix[n, m];
        }

        /// <summary>
        /// 计算字符串相似度
        /// </summary>
        /// <param name="str1"></param>
        /// <param name="str2"></param>
        /// <returns></returns>
        public float LevenshteinDistancePercent(string str1, string str2)
        {
            float maxLenth = str1.Length > str2.Length ? str1.Length : str2.Length;
            float val = Levenshtein_Distance(str1, str2);
            return 1 - val / maxLenth;
        }
    }

    #endregion 字符串匹配度查询

    #endregion 字符串
}